﻿using System.Data;
using System.Data.Common;

namespace Sunny.Core.Domain.Base.Repository
{
    /// <summary>
    /// The base of the repository
    /// </summary>
    //public abstract class RepositoryBase<T, TU, D> : IRepository<T>
    //    where T : IAggregateRoot
    //    where D : System.Data.Linq.DataContext, IDataContext
    //{
    //    #region DataContext

    //    protected D GetDataContext()
    //    {
    //        return this.GetDataContext(null);
    //    }
    //    protected D GetDataContext(IDbTransaction transaction)
    //    {
    //        var dataContext = this.InitDataContext(transaction);
    //        if(transaction != null)
    //        {
    //            dataContext.Transaction = transaction as DbTransaction;
    //            dataContext.JointOutside = true;
    //        }
    //        else
    //        {
    //            dataContext.JointOutside = false;
    //        }

    //        return dataContext;
    //    }

    //    protected abstract D InitDataContext(IDbTransaction transaction);

    //    #endregion

    //    #region Transaction

    //    protected void BeginTransaction(D dataContext)
    //    {
    //        // If the transaction is null ,that means we need to begin inside transaction
    //        // Sometimes we begin transaction in the service.
    //        if (!dataContext.JointOutside)
    //        {
    //            dataContext.Connection.Open();
    //            dataContext.Transaction = dataContext.Connection.BeginTransaction();
    //        }
    //    }

    //    protected void CommitTransaction(D dataContext)
    //    {
    //        if (!dataContext.JointOutside)
    //        {
    //            dataContext.Transaction.Commit();
    //        }
    //    }

    //    protected void RollbackTransaction(D dataContext)
    //    {
    //        if (!dataContext.JointOutside)
    //        {
    //            dataContext.Transaction.Rollback();
    //        }
    //    }

    //    #endregion

    //    #region IRepository<T> Members

    //    IAggregateRoot IRepository.GetByKey(SKey key)
    //    {
    //        return GetByKey(key);
    //    }

    //    void IRepository.Insert(IAggregateRoot model)
    //    {
    //        this.Insert((T)model);
    //    }

    //    void IRepository.Update(IAggregateRoot model)
    //    {
    //       this.Update((T)model);
    //    }

    //    void IRepository.Delete(IAggregateRoot model)
    //    {
    //        this.Delete((Model<T>)model);
    //    }

    //    void IRepository.TransactionInsert(IAggregateRoot model, IDbTransaction transaction)
    //    {
    //       this.TransactionInsert((T)model, transaction);
    //    }

    //    void IRepository.TransactionUpdate(IAggregateRoot model, IDbTransaction transaction)
    //    {
    //        this.TransactionUpdate((T)model, transaction);
    //    }

    //    void IRepository.TransactionDelete(IAggregateRoot model, IDbTransaction transaction)
    //    {
    //        this.TransactionDelete((Model<T>)model, transaction);
    //    }

    //    public virtual T GetByKey(SKey key)
    //    {
    //        using (var dataContext = this.GetDataContext())
    //        {
    //            return GetModelByKey(GetEntityBy(key, dataContext), dataContext);
    //        }
    //    }

    //    public virtual void Insert(T model)
    //    {
    //        this.TransactionInsert(model, null);
    //    }

    //    internal virtual void TransactionInsert(T model, IDbTransaction transaction)
    //    {
    //        if (model == null)
    //        {
    //            throw new RepositoryException("Model can't be null when insert model.");
    //        }

    //        model.CheckStructure();

    //        using (var dataContext = this.GetDataContext(transaction))
    //        {
    //            CheckInsertRule(model, dataContext);

    //            InsertModel(model, dataContext);
    //        }
    //    }

    //    public virtual void Update(T model)
    //    {
    //       this.TransactionUpdate(model, null);
    //    }

    //    internal virtual void TransactionUpdate(T model, IDbTransaction transaction)
    //    {
    //        if (model == null)
    //        {
    //            throw new RepositoryException("Model can't be null when update model.");
    //        }

    //        model.CheckStructure();

    //        using (var dataContext = this.GetDataContext(transaction))
    //        {
    //            var entity = GetEntityBy(model.Key, dataContext);

    //            CheckUpdateRule(model, entity, dataContext);

    //            UpdateModel(model, entity, dataContext);
    //        }
    //    }

    //    public virtual void Delete(Model<T> model)
    //    {
    //        this.TransactionDelete(model, null);
    //    }

    //    internal virtual void TransactionDelete(Model<T> model, IDbTransaction transaction)
    //    {
    //        if (model == null)
    //        {
    //            throw new RepositoryException("Model can't be null when delete model.");
    //        }

    //        using (var dataContext = this.GetDataContext(transaction))
    //        {
    //            var entity = GetEntityBy(model.Key, dataContext);

    //            CheckDeleteRule(model, entity, dataContext);

    //            DeleteModel(model, entity, dataContext);
    //        }
    //    }

    //    protected virtual void CheckInsertRule(T model, D dataContext)
    //    {
    //    }

    //    protected virtual void CheckUpdateRule(T model, TU entity, D dataContext)
    //    {
    //    }

    //    protected virtual void CheckDeleteRule(Model<T> model, TU entity, D dataContext)
    //    {
    //    }

    //    protected abstract TU GetEntityBy(SKey key, D dataContext);

    //    protected abstract T GetModelByKey(TU entity, D dataContext);

    //    protected abstract void InsertModel(T model, D dataContext);

    //    protected abstract void UpdateModel(T model, TU entity, D dataContext);

    //    protected abstract void DeleteModel(Model<T> model, TU entity, D dataContext);

    //    protected abstract T BuildModelByEntity(TU entity);

    //    #endregion

    //    #region Build Domain

    //    protected T BuildRepository<T>() where T : IRepository
    //    {
    //        return DomainFactory.GetInstance().GetRepository<T>();
    //    }

    //    protected T BuildFactory<T>() where T : FactoryBase
    //    {
    //        return DomainFactory.GetInstance().GetFactory<T>();
    //    }

    //    protected Model<T> BuildModel<T>(SKey key) where T : IAggregateRoot
    //    {
    //        return DomainFactory.GetInstance().GetModel<T>(key);
    //    }

    //    #endregion
    //}
}
